﻿using System;
using System.Collections.Generic;

namespace wuo
{
    using rehot;
    using SanlieHash;

    internal class WuoObject : IDisposable
    {
        internal object obj;
        internal Dictionary<string, string> membername_alias { get; set; }
        internal Dictionary<string, string> member_alias { get; set; }
        internal HotObject _hot;
        public WuoObject(object obj)
        {
            this.membername_alias = new Dictionary<string, string>();
            this.member_alias = new Dictionary<string, string>();
            this.obj = obj;
            _hot = new HotObject(obj);

            foreach (var id in _hot.Type.Members.AllMemberId())
            {
                var attr_id = _hot.Type.Attributes.FindAttributeId(id, "WuoProperty");
                if (attr_id != string.Empty)
                {
                    var attr = _hot.Type.Attributes.ReadAttributeById(attr_id);
                    if (attr.ExistMember("PropertyName"))
                    {
                        var wuoname = attr.Read<string>("PropertyName");
                        if (!string.IsNullOrEmpty(wuoname))
                        {
                            membername_alias.Add(id, wuoname);
                            var alias_id = FastHash.GetSM3(wuoname);
                            member_alias.Add(alias_id, id);
                            continue;
                        }
                    }
                }
                membername_alias.Add(id, _hot.Type.Members.ReadNameById(id));
            }
        }
        public WuoObject(Type t) : this(Activator.CreateInstance(t)) { }
        public void write(string name, object? obj)
        {
            var id = _hot.Type.Members.FindMemberId(name);
            if (id != string.Empty && _hot.Type.Members.CanWrite(id)) _hot.Type.Members.SetObjByMemberId(this.obj, id, obj);
            else
            {
                var alias_id = FastHash.GetSM3(name);
                if (member_alias.ContainsKey(alias_id) && _hot.Type.Members.CanWrite(member_alias[alias_id])) _hot.Type.Members.SetObjByMemberId(this.obj, member_alias[alias_id], obj);
            }
        }
        public object? read(string name)
        {
            var id = _hot.Type.Members.FindMemberId(name);
            if (id != string.Empty && _hot.Type.Members.CanRead(id)) return _hot.Type.Members.GetByMemberId(this.obj, id);
            var alias_id = FastHash.GetSM3(name);
            if (member_alias.ContainsKey(alias_id) && _hot.Type.Members.CanRead(member_alias[alias_id])) return _hot.Type.Members.GetByMemberId(this.obj, member_alias[alias_id]);
            return null;
        }

        public IEnumerable<string> LoopPropNames()
        {
            foreach (var id in _hot.Type.Members.AllMemberId()) if (membername_alias.ContainsKey(id)) yield return membername_alias[id];
        }
        public object ToObject()
        {
            return obj;
        }

        public void Dispose()
        {
            if (this._hot != null) this._hot.Dispose();
            if (membername_alias != null) membername_alias.Clear();
            if (member_alias != null) member_alias.Clear();
            this._hot = null;
            this.member_alias = null;
            this.membername_alias = null;
        }
    }
}
